home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / graphics.17 / graphics / graphics-0.17 / plot2tek / plot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-12  |  12.2 KB  |  511 lines

  1. /* This program, plot, translates a GNU plot file into device specific output.
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. Plot is distributed in the hope that it will be useful, but WITHOUT
  5. ANY WARRANTY.  No author or distributor accepts responsibility to
  6. anyone for the consequences of using it or for whether it serves any
  7. particular purpose or works at all, unless he says so in writing.
  8. Refer to the GNU General Public License for full details.
  9.  
  10. Everyone is granted permission to copy, modify and redistribute plot,
  11. but only under the conditions described in the GNU General Public
  12. License.  A copy of this license is supposed to have been given to you
  13. along with plot so you can know your rights and responsibilities.  It
  14. should be in a file named COPYING.  Among other things, the copyright
  15. notice and this notice must be preserved on all copies.  */
  16.  
  17. /* This file is the main routine for plot.
  18.  
  19.    It includes code to read the plot file and call plot functions
  20.    to draw the graphics. */
  21.  
  22. #include "sys-defines.h"
  23. #include "libplot.h"
  24. #include "getopt.h"
  25. #include "../COPYING"
  26.  
  27. enum plot_instruction
  28. {
  29.   ALABEL =    'T',
  30.   ARC =        'a',
  31.   CIRCLE =    'c',
  32.   COLOR =    'C',
  33.   CONT =    'n',
  34.   ERASE =    'e',
  35.   FILL =    'L',
  36.   FONT =    'F',
  37.   FONTSIZE =    'S',
  38.   LABEL =    't',
  39.   LINE =    'l',
  40.   LINEMOD =    'f',
  41.   MOVE =    'm',
  42.   POINT =    'p',
  43.   ROTATE =    'r',
  44.   SPACE =    's',
  45. };
  46.  
  47. /* This flag specifies that the input contains unsigned (if zero) or
  48.    signed (if nonzero) two byte intgers. The default is signed. */
  49. int signed_input = 1;
  50.  
  51. /* read in two byte intgers with high_byte_first. The default is to read the low
  52.    byte first. */
  53. int high_byte_first = 0;
  54.  
  55. /* guess_byte_order is a flag which, if non-zero, indicated that the function
  56.    find_byte_order should be used to guess the byte order for the input file. */
  57. int guess_byte_order = 1;
  58.  
  59. /* swap_bytes returns the bottom two bytes of its integer argument with
  60.    their bytes reversed. */
  61.  
  62. int
  63. swap_bytes (x)
  64.      int x;
  65. {
  66.   unsigned char a, b;
  67.   a = x & 0xff;
  68.   b = (x >> 8) & 0xff;
  69.   return ((a << 8)|b);
  70. }
  71.  
  72. /* This is a set of known values for the maximum x (abscissa) values
  73.    specified in the plot size command for known devices.  Using this
  74.    set we can construct a heuristic proceedure for recognizing plot
  75.    files in which the bytes of two byte integers are reversed.  We can
  76.    recognize these files by looking for size commands containing these
  77.    known sizes in byte reversed form. The last entry should be 0. */
  78.    
  79. int known_size[32] = {
  80.   504,                /* plot3d output 504x504 */
  81.   2048,                /* versatek plotter 2048x2048 */
  82.   2100,                /* plot3d output */
  83.   3120,                /* Tektronix 4010 terminal 3120x3120 */
  84.   4096,                /* GSI 300 terminal 4096x4096 */
  85.   0                /* the last entry should be 0 */
  86.   };
  87.  
  88. /* find_byte_order takes four integer arguments and matches third one
  89.    against a set of known values (sizes, see above). If there is a match
  90.    it merely returns.  If there is no match, it check each of the values
  91.    again with the bottom two bytes reversed. If such a match is found, the
  92.    bottom two bytes of each argument is reversed, the high_byte_first flag
  93.    is inverted to indicated how two byte integers should be read and the
  94.    runction returns. */
  95.    
  96. void
  97. find_byte_order (x0, y0, x1, y1)
  98.      int *x0, *y0, *x1, *y1;
  99. {
  100.   int i;
  101.   for (i=0; known_size[i]!=0; i++)
  102.     {
  103.       if (*x1 == known_size[i])
  104.     return;
  105.     }
  106.   /* now check to see if reversing the bytes allows a match... */
  107.   for (i=0; known_size[i]!=0; i++)
  108.     {
  109.       if (*x1 == swap_bytes (known_size[i]))
  110.     {
  111.       *x0 = swap_bytes (*x0);
  112.       *y0 = swap_bytes (*y0);
  113.       *x1 = swap_bytes (*x1);
  114.       *y1 = swap_bytes (*y1);
  115.       high_byte_first = ! high_byte_first;
  116.       return;
  117.     }
  118.     }
  119.  
  120.   /* finally, if none of this works, just assume that x1 > 128. */
  121.   if ((*x1 < 128) && (swap_bytes (*x1) > 128))
  122.     {
  123.       *x0 = swap_bytes (*x0);
  124.       *y0 = swap_bytes (*y0);
  125.       *x1 = swap_bytes (*x1);
  126.       *y1 = swap_bytes (*y1);
  127.       high_byte_first = ! high_byte_first;
  128.       return;
  129.     }
  130. }
  131.  
  132. /* Read a byte */
  133.  
  134. #define read_byte(stream) (getc (stream))
  135.  
  136. /* Read a coordinate - a two byte integer. */
  137.   
  138. int coord (input)
  139.      FILE *input;
  140. {
  141.   int x;
  142.   if ( high_byte_first )
  143.     {
  144.       x = ((char) read_byte (input)) << 8; /* get sign from high byte */
  145.       x |= read_byte (input) & 0xFF; /* not from low byte */
  146.     }
  147.   else
  148.     {
  149.       x = read_byte (input) & 0xFF; /* ingnore sign in low byte */
  150.       x |= ((char) read_byte (input)) << 8; /* get sign from high byte */
  151.     }
  152.   if ( ! signed_input )
  153.     {
  154.       x &= 0xFFFF;
  155.     }
  156.  
  157.   return x;
  158. }
  159.   
  160. /*  Read a string, change termination to null.
  161.     note: string (buffer) reads a newline terminated string. */
  162.  
  163. void
  164. read_string (input, buffer, buffer_length)
  165.      FILE *input;
  166.      char *buffer;
  167.      int buffer_length;
  168. {
  169.   int length=0;
  170.   char termination = '\n';
  171.   char c = '\0';
  172.  
  173.   while (!feof (input))
  174.     {
  175.       if (length > buffer_length)
  176.     {
  177.       buffer_length *= 2;
  178.       buffer = (char *) realloc (buffer, buffer_length);
  179.       if (buffer <= (char *) 0)
  180.         {
  181.           closepl ();
  182.           perror ("realloc failed:");
  183.           exit (-1);
  184.         }
  185.     }
  186.       c = read_byte (input);
  187.       if (c == termination)
  188.     break;
  189.       buffer [length++] = c;
  190.     }
  191.  
  192.   buffer [length] = '\0';    /*  null terminate label */
  193. }
  194.  
  195.  
  196. /* read_plot reads a plot file from the standard input and calls
  197.    a plot function according to each plot instruction found in the
  198.    file. */
  199.  
  200. void
  201. read_plot (in_stream, buffer, buffer_length)
  202.      FILE *in_stream;
  203.      char *buffer;
  204.      int  buffer_length;
  205. {
  206.   char x_adjust, y_adjust;
  207.   int x0, y0, x1, y1, x2, y2;
  208.   int instruction;
  209.  
  210.   instruction = read_byte (in_stream);
  211.   while (!feof (in_stream))
  212.     {
  213.       switch (instruction)
  214.     {
  215.       /*  Note: we must get all but the last argument before calling to
  216.           ensure reading them in the proper order. */
  217.       
  218.     case ALABEL:
  219.       x_adjust = read_byte (in_stream);
  220.       y_adjust = read_byte (in_stream); 
  221.       read_string (in_stream, buffer, buffer_length);
  222.       alabel (x_adjust, y_adjust, buffer);
  223.       break;
  224.     case ARC:
  225.       x0 = coord (in_stream);
  226.       y0 = coord (in_stream);
  227.       x1 = coord (in_stream);
  228.       y1 = coord (in_stream); 
  229.       x2 = coord (in_stream);
  230.       y2 = coord (in_stream); 
  231.       arc (x0, y0, x1, y1, x2, y2);
  232.       break;
  233.     case CIRCLE:
  234.       x0 = coord (in_stream);
  235.       y0 = coord (in_stream);
  236.       x1 = coord (in_stream);
  237.       circle (x0, y0, x1);
  238.       break;
  239.     case COLOR:
  240.       x0 = coord (in_stream)&0xFFFF;
  241.       y0 = coord (in_stream)&0xFFFF;
  242.       x1 = coord (in_stream)&0xFFFF;
  243.       color (x0, y0, x1);
  244.       break;
  245.     case CONT:
  246.       x0 = coord (in_stream);
  247.       y0 = coord (in_stream);
  248.       cont (x0, y0);
  249.       break;
  250.     case ERASE:
  251.       erase ();
  252.       break;
  253.     case FILL:
  254.       fill (coord (in_stream)&0xFFFF); break;
  255.     case FONT:
  256.       read_string (in_stream, buffer, buffer_length);
  257.       fontname (buffer);
  258.       break;
  259.     case FONTSIZE:
  260.       fontsize (coord (in_stream));
  261.       break;
  262.     case LABEL:
  263.       read_string (in_stream, buffer, buffer_length);
  264.       label (buffer);
  265.       break;
  266.     case LINE:
  267.       x0 = coord (in_stream);
  268.       y0 = coord (in_stream);
  269.       x1 = coord (in_stream);
  270.       y1 = coord (in_stream); 
  271.       line (x0, y0, x1, y1);
  272.       break;
  273.     case LINEMOD:
  274.       read_string (in_stream, buffer, buffer_length);
  275.       linemod (buffer);
  276.       break;
  277.     case MOVE:
  278.       x0 = coord (in_stream);
  279.       y0 = coord (in_stream);
  280.       move (x0, y0);
  281.       break;
  282.     case POINT:
  283.       x0 = coord (in_stream);
  284.       y0 = coord (in_stream);
  285.       point (x0, y0);
  286.       break;
  287.     case ROTATE:
  288.       x0 = coord (in_stream);
  289.       y0 = coord (in_stream);
  290.       x1 = coord (in_stream);
  291.       rotate (x0, y0, x1);
  292.       break;
  293.     case SPACE:
  294.       x0 = coord (in_stream);
  295.       y0 = coord (in_stream);
  296.       x1 = coord (in_stream);
  297.       y1 = coord (in_stream); 
  298.       if (guess_byte_order)
  299.         find_byte_order (&x0, &y0, &x1, &y1);
  300.       space (x0, y0, x1, y1);
  301.       break;
  302.     default:
  303.       fprintf (stderr, "Unrecognized plot command `%c' ignored.\n", instruction);
  304.     }
  305.       instruction = read_byte (in_stream);
  306.     }
  307.   return;
  308. }
  309.  
  310. char *progname;            /* argv[0] or the name of this program */
  311.  
  312. void
  313. display_version ()
  314. {
  315.     (void) fprintf (stderr, "\
  316. %s version %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\
  317. plot comes with ABSOLUTELY NO WARRANTY; type `%s +warranty'\n\
  318. for details.  This is free software, and you are welcome to redistribute\n\
  319. it; Type `plot2ps +copying' to view the copying conditions.\n",
  320.             progname, VERS, progname);
  321. }
  322.  
  323. /* Long options we recognize */
  324. #define    ARG_NONE    0
  325. #define    ARG_REQUIRED    1
  326. #define    ARG_OPTIONAL    2
  327.  
  328. struct option    long_options[] = {
  329.     { "fontsize",    ARG_REQUIRED,    NULL, 'f' },
  330.     { "fontname",    ARG_REQUIRED,    NULL, 'F' },
  331.     { "high-byte-first", ARG_NONE,    NULL, 'h' },
  332.     { "low-byte-first",    ARG_NONE,    NULL, 'l' },
  333.     { "signed-input",    ARG_NONE,    NULL, 's' },
  334.     { "unsigned-input",    ARG_NONE,    NULL, 'u' },
  335.     { "warranty",    ARG_NONE,    NULL, 'W' },
  336.     { "copying",    ARG_NONE,    NULL, 'C' },
  337.     { "help",        ARG_NONE,    NULL, 'H' },
  338.     { "version",    ARG_NONE,    NULL, 'V' },
  339.     { NULL,        0,        NULL, 0}
  340. };
  341.  
  342. void
  343. display_help ()
  344. {
  345.   int i;
  346.   fprintf (stderr, "usage: %s", progname);
  347.   for (i=0; long_options[i].name; i++)
  348.     {
  349.       fprintf (stderr, " [+%s", long_options[i].name);
  350.       if (isprint (long_options[i].val))
  351.     fprintf (stderr, "|-%c", long_options[i].val);
  352.       if (long_options[i].has_arg == ARG_REQUIRED)
  353.     fprintf (stderr, " arg]");
  354.       else
  355.     fprintf (stderr, "]");
  356.     }
  357.   fprintf (stderr, "\n");
  358. }
  359.  
  360.  
  361. int
  362. main (argc, argv)
  363.      int argc;
  364.      char *argv[];
  365. {
  366.   int option;
  367.   int opt_index;
  368.   int errcnt = 0;            /* errors encountered */
  369.   int show_version = 0;        /* remember to show version message */
  370.   int show_usage = 0;        /* remember whether to output usage message. */
  371.   int show_copying = 0;        /* remember to show copying conditions */
  372.   int named_input = 0;        /* count named plot files on command line. */
  373.   char *buffer;
  374.   int  buffer_length;
  375.  
  376.   progname = argv[0];
  377.   buffer_length = 1024;
  378.   buffer = (char *) malloc (buffer_length);
  379.   if (buffer <= (char *) 0)
  380.     {
  381.       perror ("malloc failed:");
  382.       exit (-1);
  383.     }
  384.  
  385.   openpl ();
  386.  
  387. while ((option = getopt_long (argc, argv, "-CF:HVWf:hlsu", long_options, &opt_index)) != EOF) {
  388.       if (option == 0)
  389.     option = long_options[opt_index].val;
  390.  
  391.       switch (option)
  392.     {
  393.     case 'f':
  394.       /* Sizes supported by X: 8, 10, 12, 14, 18, and 24. */
  395.       (void) fontsize (atoi (optarg));
  396.     case 'F':
  397.       (void) fontname (optarg);
  398.       break;
  399.     case 'h':        /* read high byte first */
  400.       guess_byte_order = 0;
  401.       high_byte_first = 1;
  402.       break;
  403.     case 'l':        /* read low byte first */
  404.       guess_byte_order = 0;
  405.       high_byte_first = 0;
  406.       break;
  407.     case 's':        /* Signed */
  408.       signed_input = 1;
  409.       break;
  410.     case 'u':        /* Unsigned */
  411.       signed_input = 0;
  412.       break;
  413.     case 'H':        /* Help */
  414.       show_usage = 1;
  415.       break;
  416.     case 'v':
  417.     case 'V':        /* Version */
  418.       show_version = 1;
  419.       break;
  420.     case 'W':        /* Warranty */
  421.     case 'C':        /* Copying */
  422.       show_copying = 1;
  423.       break;
  424.     case 1:
  425.       {
  426.         FILE *data_file;
  427.  
  428.         if (strcmp (optarg, "-") == 0)
  429.           data_file = stdin;
  430.         else
  431.           {
  432.         data_file = fopen (optarg, "r");
  433.         if (data_file == NULL)
  434.           {
  435.             (void) fprintf (stderr, "%s:  ignoring nonexistent or inaccessible file `%s'\n",
  436.                     argv[0], optarg);
  437.             continue;
  438.           }
  439.           }
  440.         read_plot (data_file, buffer, buffer_length);
  441.         named_input++;
  442.  
  443.         if (data_file != stdin) /* Don't close stdin */
  444.           fclose (data_file);
  445.       }
  446.       break;
  447.     default:
  448.       errcnt++;
  449.       break;
  450.     }
  451.     }
  452.  
  453.   if (show_version)
  454.     display_version ();
  455.  
  456.   if (errcnt > 0 || show_usage)
  457.     display_help ();
  458.  
  459.   if (show_copying)
  460.     {
  461.       int k;
  462.       if (!show_version)
  463.     display_version ();
  464.       for (k = 0; copy_notice[k] != '\0'; k++) {
  465.     (void) fputs (copy_notice[k], stderr);
  466.       }
  467.       closepl ();
  468.       exit (0);
  469.     }
  470.  
  471.   if (errcnt > 0 || show_usage)
  472.     {
  473.       closepl ();
  474.       exit (errcnt > 0 ? 1 : 0);
  475.     }
  476.  
  477.  
  478.   if (optind < argc)
  479.     {
  480.       for (; optind < argc; optind++)
  481.     {
  482.       FILE *data_file;
  483.  
  484.       if (strcmp (argv[optind], "-") == 0)
  485.         data_file = stdin;
  486.       else
  487.         {
  488.           data_file = fopen (argv[optind], "r");
  489.           if (data_file == NULL)
  490.         {
  491.           (void) fprintf (stderr, "%s:  ignoring nonexistent or inaccessible file `%s'\n",
  492.                   argv[0], argv[optind]);
  493.           continue;
  494.         }
  495.         }
  496.       named_input++;
  497.       read_plot (stdin, buffer, buffer_length);
  498.  
  499.       if (data_file != stdin) /* Don't close stdin */
  500.         fclose (data_file);
  501.     }
  502.     } /* endfor */
  503.  
  504.   if (!named_input)
  505.     /* Read stdin if no files were named on the command line. */
  506.     read_plot (stdin, buffer, buffer_length);
  507.  
  508.   closepl ();
  509.   return 0;
  510. }
  511.